/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * File Name          : freertos.c
  * Description        : Code for freertos applications
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2025 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/
#include "FreeRTOS.h"
#include "task.h"
#include "main.h"
#include "cmsis_os.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include <stdio.h>
#include <string.h>
#include "aht20.h"
#include <math.h>
/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN Variables */
extern ADC_HandleTypeDef hadc1;
extern UART_HandleTypeDef huart2;
SensorData g_sensor_data;

// 2. 定义事件标志组句柄
osEventFlagsId_t TempEventHandle;

// 3. 定义数据互斥锁句柄
osMutexId_t DataMutexHandle;
// 消息队列句柄定义（新增）
osMessageQueueId_t UartMsgQueueHandle;
/* USER CODE END Variables */
/* Definitions for CompareTask */
osThreadId_t CompareTaskHandle;
const osThreadAttr_t CompareTask_attributes = {
  .name = "CompareTask",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityAboveNormal,
};
/* Definitions for AHT20Task */
osThreadId_t AHT20TaskHandle;
const osThreadAttr_t AHT20Task_attributes = {
  .name = "AHT20Task",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for NCTTask */
osThreadId_t NCTTaskHandle;
const osThreadAttr_t NCTTask_attributes = {
  .name = "NCTTask",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};
/* Definitions for UartSendTask */
osThreadId_t UartSendTaskHandle;
const osThreadAttr_t UartSendTask_attributes = {
  .name = "UartSendTask",
  .stack_size = 512 * 4,
  .priority = (osPriority_t) osPriorityNormal,
};

/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN FunctionPrototypes */
void StartUartSendTask(void *argument);
/* USER CODE END FunctionPrototypes */

void StartCompareTask(void *argument);
void StartAHT20Task(void *argument);
void StartNCTTask(void *argument);
void StartUartSendTask(void *argument);

void MX_FREERTOS_Init(void); /* (MISRA C 2004 rule 8.1) */

/**
  * @brief  FreeRTOS initialization
  * @param  None
  * @retval None
  */
void MX_FREERTOS_Init(void) {
  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* USER CODE BEGIN RTOS_MUTEX */
	osMutexAttr_t mutex_attr = {
	    .name = "DataMutex",
	    .attr_bits = osMutexPrioInherit  // 关键：启用优先级继承
	  };
	  DataMutexHandle = osMutexNew(&mutex_attr);
	  if (DataMutexHandle == NULL) {
	    Error_Handler();  // 若创建失败，进入错误处理
	  }
  /* USER CODE END RTOS_MUTEX */

  /* USER CODE BEGIN RTOS_SEMAPHORES */
  /* add semaphores, ... */
  /* USER CODE END RTOS_SEMAPHORES */

  /* USER CODE BEGIN RTOS_TIMERS */
  /* start timers, add new ones, ... */
  /* USER CODE END RTOS_TIMERS */

  /* USER CODE BEGIN RTOS_QUEUES */
	  osMessageQueueAttr_t queue_attr = {
	     .name = "UartMsgQueue"
	   };
	   UartMsgQueueHandle = osMessageQueueNew(
	     UART_QUEUE_LENGTH,    // 队列长度
	     UART_QUEUE_ITEM_SIZE, // 每个项大小
	     &queue_attr           // 队列属性
	   );
	   if (UartMsgQueueHandle == NULL) Error_Handler();  // 创建失败处理
  /* USER CODE END RTOS_QUEUES */

  /* Create the thread(s) */
  /* creation of CompareTask */
  CompareTaskHandle = osThreadNew(StartCompareTask, NULL, &CompareTask_attributes);

  /* creation of AHT20Task */
  AHT20TaskHandle = osThreadNew(StartAHT20Task, NULL, &AHT20Task_attributes);

  /* creation of NCTTask */
  NCTTaskHandle = osThreadNew(StartNCTTask, NULL, &NCTTask_attributes);

  /* creation of UartSendTask */
  UartSendTaskHandle = osThreadNew(StartUartSendTask, NULL, &UartSendTask_attributes);

  /* USER CODE BEGIN RTOS_THREADS */
    if (UartSendTaskHandle == NULL) {
      // 若任务创建失败，强制输出错误信息
      HAL_UART_Transmit(&huart2, (uint8_t*)"UartSendTask Create FAIL\r\n", 26, 100);
    } else {
      HAL_UART_Transmit(&huart2, (uint8_t*)"UartSendTask Create OK\r\n", 24, 100);
    }
  /* USER CODE END RTOS_THREADS */

  /* USER CODE BEGIN RTOS_EVENTS */
  TempEventHandle = osEventFlagsNew(NULL);
    if (TempEventHandle == NULL) {
      Error_Handler();  // 若创建失败，进入错误处理
    }
  /* USER CODE END RTOS_EVENTS */

}

/* USER CODE BEGIN Header_StartCompareTask */
/**
  * @brief  Function implementing the CompareTask thread.
  * @param  argument: Not used
  * @retval None
  */
/* USER CODE END Header_StartCompareTask */
void StartCompareTask(void *argument)
{
  /* USER CODE BEGIN StartCompareTask */
//	HAL_UART_Transmit(&huart2, (uint8_t*)"比较任务启动\r\n", 16, 100);  // 新增
//	osDelay(10);
	uint32_t event_flags;
	  // 1. 新增：消息队列数据变量（替换原有单独的 temp_diff、log_msg）
	  UartMsg uart_msg;  // 对应 main.h 中定义的消息结构体
  /* Infinite loop */
  for(;;)
  {
	  event_flags = osEventFlagsWait(
	        TempEventHandle,
	        EVENT_AHT_DONE | EVENT_NTC_DONE,
	        osFlagsWaitAll,  // 保持不变（后续手动清标志）
	        osWaitForever
	      );

	      if ((event_flags & (EVENT_AHT_DONE | EVENT_NTC_DONE)) == (EVENT_AHT_DONE | EVENT_NTC_DONE))
	      {
//	    	  // 新增：验证是否进入比较逻辑
//	    	    HAL_UART_Transmit(&huart2, (uint8_t*)"Enter Compare Logic\r\n", 20, 100);
//	    	    osDelay(10);  // 避免发送冲突
	        osMutexAcquire(DataMutexHandle, osWaitForever);
	        // 2. 直接读取数据到消息结构体中（无需单独定义 temp_diff）
	        uart_msg.sensor_data.aht_temp = g_sensor_data.aht_temp;
	        uart_msg.sensor_data.aht_hum = g_sensor_data.aht_hum;
	        uart_msg.sensor_data.ntc_temp = g_sensor_data.ntc_temp;
	        // 3. 计算差值并存入消息
	        uart_msg.sensor_data.temp_diff = uart_msg.sensor_data.aht_temp - uart_msg.sensor_data.ntc_temp;
	        osMutexRelease(DataMutexHandle);

	        // 4. 格式化日志字符串到消息的 log_str 字段（替换原有 log_msg）
	        sprintf(uart_msg.log_str,
	                "数据记录：AHT温 = %.1f℃ | 湿 = %.1f%% | NTC温 = %.1f℃ | 差值 = %.1f℃ ^_^\n",
	                uart_msg.sensor_data.aht_temp,
	                uart_msg.sensor_data.aht_hum,
	                uart_msg.sensor_data.ntc_temp,
	                uart_msg.sensor_data.temp_diff);
	        osDelay(20);
	        // 5. 新增：将消息写入队列（关键！给串口任务发数据）
	        osMessageQueuePut(
	          UartMsgQueueHandle,  // 消息队列句柄（main.h 中声明）
	          &uart_msg,           // 要发送的消息数据
	          0,                   // 消息优先级（0即可）
	          100                  // 超时时间（100ms，避免阻塞）
	        );
//	        HAL_UART_Transmit(&huart2, (uint8_t*)"Message Put Queue\r\n", 18, 100);
//	          osDelay(10);
	        // 原有：手动清除事件标志（不变）
	        osEventFlagsClear(TempEventHandle, EVENT_AHT_DONE | EVENT_NTC_DONE);
	      }
	    }
  /* USER CODE END StartCompareTask */
}

/* USER CODE BEGIN Header_StartAHT20Task */
/**
* @brief Function implementing the AHT20Task thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartAHT20Task */
void StartAHT20Task(void *argument)
{
  /* USER CODE BEGIN StartAHT20Task */
//	HAL_UART_Transmit(&huart2, (uint8_t*)"AHT20任务启动\r\n", 16, 100);
//	osDelay(10);
  AHT20_Init();  // 初始化传感器

  /* Infinite loop */
  for(;;)
  {
	    char msg_temp[50];        // 温度字符串缓存
	    char msg_hum[50];         // 湿度字符串缓存
	  /* 3. 触发AHT20测量 */
	      AHT20_Measure();  // 启动测量（具体看AHT20库实现，若需等待测量完成可加短延时）

	      /* 4. 读取温湿度数据 */
	      float temperature = AHT20_Temperature();  // 获取温度
	      float humidity = AHT20_Humidity();        // 获取湿度

	      /* 5. 格式化字符串（开启浮点支持后可用） */
	      sprintf(msg_temp, "温度:%.1f℃", temperature);
	      sprintf(msg_hum, "湿度:%.1f%%", humidity);
	      // 若需要打印，可加串口输出（如HAL_UART_Transmit(&huart1, (uint8_t*)msg_temp, strlen(msg_temp), 100);）
	      //HAL_UART_Transmit(&huart2, (uint8_t*)msg_temp, strlen(msg_temp), 100);  // 临时输出
	      //osDelay(100);
	      /* 6. 保护并更新全局数据（通过互斥锁避免冲突） */
	      osMutexAcquire(DataMutexHandle, osWaitForever);  // 申请互斥锁
	      g_sensor_data.aht_temp = temperature;            // 更新全局温度
	      g_sensor_data.aht_hum = humidity;                // 更新全局湿度
	      osMutexRelease(DataMutexHandle);                  // 释放互斥锁

	      /* 7. 设置AHT20读取完成事件（通知比较任务） */
	      osEventFlagsSet(TempEventHandle, EVENT_AHT_DONE);

	      /* 8. 延时1000ms+（满足“读取间隔>1秒”要求，可调整为1500ms更稳妥） */
	      osDelay(1500);  // RTOS延时，单位ms（非1000s！之前笔误，传感器读取不需要1000秒）
  }
  /* USER CODE END StartAHT20Task */
}

/* USER CODE BEGIN Header_StartNCTTask */
/**
* @brief Function implementing the NCTTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartNCTTask */
void StartNCTTask(void *argument)
{
  /* USER CODE BEGIN StartNCTTask */
//	HAL_UART_Transmit(&huart2, (uint8_t*)"NCT任务启动\r\n", 18, 100);  // 新增
//	osDelay(10);
	int32_t adc_value = 0;
	float ntc_resistance = 0.0f;
	float voltage = 0.0f;
	float ntc_temp = 0.0f;
	char message[50] = {0};  // 正确声明字符串数组
	if (HAL_ADCEx_Calibration_Start(&hadc1) != HAL_OK) {
	    Error_Handler();  // 校准失败则进入错误处理
	  }
  /* Infinite loop */
  for(;;)
  {
	  osMutexAcquire(DataMutexHandle, osWaitForever);
	          // 启动ADC1_IN4转换
	          HAL_ADC_Start(&hadc1);
	          // 等待转换完成
	          if (HAL_ADC_PollForConversion(&hadc1, 50) == HAL_OK) {
	              // 读取IN4通道的ADC值
	              adc_value = HAL_ADC_GetValue(&hadc1);
	              // 转换为电压值（假设ADC参考电压3.3V，12位ADC）
	              voltage = (float)adc_value * 3.3f / 4095.0f;

	              // 计算NTC电阻值（分压电路：NTC与R_REF串联，采集NTC两端电压）
	              ntc_resistance = NTC_R_REF * voltage / (3.3f - voltage);
	              // 基于B值计算温度（转换为摄氏度）
	              ntc_temp = 1 / ((1 / NTC_T_REF) + (log(ntc_resistance / NTC_R_REF) / NTC_B_VALUE)) - 273.15f;

	              // 更新全局传感器数据
	              g_sensor_data.ntc_temp = ntc_temp;

	              // 格式化数据并串口发送
	              sprintf(message, "NTC Temp: %.1f℃\r\n", ntc_temp);
	              //HAL_UART_Transmit(&huart1, (uint8_t *)message, strlen(message), 100);
	              //HAL_UART_Transmit(&huart2, (uint8_t*)message, strlen(message), 100);  // 临时输出
	              //osDelay(100);
	          }
	          HAL_ADC_Stop(&hadc1);

	          osMutexRelease(DataMutexHandle);
	          // 触发NTC读取完成事件
	          osEventFlagsSet(TempEventHandle, EVENT_NTC_DONE);
	          // 延时500ms（你之前写的500s应为笔误，实际监测500ms更合理）
	          osDelay(500);
  }
  /* USER CODE END StartNCTTask */
}

/* USER CODE BEGIN Header_StartUartSendTask */
/**
* @brief Function implementing the UartSendTask thread.
* @param argument: Not used
* @retval None
*/
/* USER CODE END Header_StartUartSendTask */
void StartUartSendTask(void *argument)
{
  /* USER CODE BEGIN StartUartSendTask */
	HAL_UART_Transmit(&huart2, (uint8_t*)"UartSendTask BEGIN\r\n", 20, 100);
	  osDelay(10);  // 确保发送完成
	UartMsg recv_msg;  // 接收队列消息（对应main.h中定义的结构体）
	HAL_StatusTypeDef uart_status;

  /* Infinite loop */
  for(;;)
  {
	  // 新增：提示正在等待队列数据
//	      HAL_UART_Transmit(&huart2, (uint8_t*)"Waiting Queue...\r\n", 18, 100);
//	      osDelay(500);  // 每隔500ms提示一次，避免刷屏
	  if (osMessageQueueGet(
	            UartMsgQueueHandle,  // 消息队列句柄
	            &recv_msg,           // 接收数据缓冲区
	            NULL,                // 不关心消息发送者优先级
	            osWaitForever        // 永久等待，无超时
	          ) == osOK)
	      {
//		  // 新增：验证成功读取队列数据
//		        HAL_UART_Transmit(&huart2, (uint8_t*)"Get Queue Data\r\n", 18, 100);
//		        osDelay(10);
	        // 读取成功，通过UART1发送格式化后的字符串
	        uart_status = HAL_UART_Transmit(
	          &huart2,                  // UART句柄（确保main.c中已初始化huart1）
	          (uint8_t*)recv_msg.log_str,  // 要发送的字符串（CompareTask中格式化完成）
	          strlen(recv_msg.log_str),    // 字符串长度
	          100                       // 发送超时时间（100ms）
	        );

	        // 串口发送失败处理（可选，增强稳定性）
	        if (uart_status != HAL_OK) {
	          // 发送失败提示（简短字符串，避免占用过多资源）
	          HAL_UART_Transmit(&huart2, (uint8_t*)"UART Send Fail\r\n", 16, 100);
	        }
	      }
	   }
  /* USER CODE END StartUartSendTask */
}

/* Private application code --------------------------------------------------*/
/* USER CODE BEGIN Application */

/* USER CODE END Application */

